/**
 * websocket处理封装
 * @author X.Mo <root@imoi.cn>
 */
import tool from '@/utils/tool'
import SysConfig from '@/config'
class webSocket {
  /**
   * websocket 连接句柄
   * @var Websocket
   */
  ws = null

  /**
   * 服务器地址
   * @var
   */
  serverUrl = SysConfig.WS_URL

  /**
   * 心跳配置
   * @var object
   */
  heartbeat = {
    openHeartbeat: false,    // 是否开启心跳
    interval: 10 * 1000     // 心跳发送间隔，默认10秒
  }

  /**
   * 重连配置
   * @var object
   */
  reconnectConfig = {
    isReconnect: true,    // 是否开启短线重连
    timer: null,          // 计时器对象
    interval: 5 * 1000,   // 重连间隔时间
    retry: -1,            // 重连次数
  }

  /**
   * ws事件
   * @var Array
   */
  onEvent = {}

  /**
   * 原生 websocket 事件
   */
  events = {
    onOpen: e => { e; },
    onClose: e => { e; },
    onError: e => { e; },
  }

  /**
   * 构造函数
   */
  constructor() {
    this.onEvent = {};
    if (tool.data.get("TOKEN"))
      this.connection();
  }

  /**
   * 绑定事件
   */
  on(ev, callback) {
    this.onEvent[ev] = callback
  }
  /**
   * 绑定事件
   */
  off(ev) {
    delete this.onEvent[ev];
  }

  /**
   * 连接websocket
   */
  connection() {
    if (this.ws) {
      this.ws.close()
      this.ws = null
    }
    this.ws = new WebSocket(this.serverUrl + '?token=' + tool.data.get("TOKEN"))
    this.ws.onopen = this.onOpen.bind(this)
    this.ws.onerror = this.onError.bind(this)
    this.ws.onmessage = this.onMessage.bind(this)
    this.ws.onclose = this.onClose.bind(this)
  }

  /**
   * 解析数据
   *
   * @param {Object} evt Websocket 消息
   */
  onParseData(evt) {
    return JSON.parse(evt.data)
  }

  /**
   * 打开连接
   *
   * @param {Object} evt Websocket 消息
   */
  onOpen(evt) {
    this.events.onOpen(evt)
    this.sendHeartbeat()
  }

  /**
   * 关闭连接
   *
   * @param {Object} evt Websocket 消息
   */
  onClose(evt) {
    clearInterval(this.heaerbeatTimer)

    if (evt.code == 1006) {
      this.reconnect()
    }

    this.events.onClose(evt)
  }

  /**
   * 连接错误
   *
   * @param {Object} evt Websocket 消息
   */
  onError(evt) {
    this.events.onError(evt)
  }

  /**
   * 接收消息
   *
   * @param {Object} evt Websocket 消息
   */
  onMessage(evt) {

    let result = this.onParseData(evt)
    if (result.data == 'PING') {
      this.ws.send('PONG');
      return;
    }
    if (typeof this.onEvent[result.event] == 'function') {

      this.onEvent[result.event](result)

    }

  }

  /**
   * 向服务器发送心跳数据包
   */
  sendHeartbeat() {
    if (this.heartbeat.openHeartbeat) {
      setInterval(() => {
        this.ws.send('PONG')
      }, this.heartbeat.interval)
    }
  }

  /**
   * 短线重连
   */
  reconnect() {
    let reconnect = this.reconnectConfig
    if (!reconnect.isReconnect || reconnect.retry == 0) {
      return
    }
    this.reconnectConfig.isReconnect = false
    reconnect.timer && clearTimeout(reconnect.timer)
    this.reconnectConfig.timer = setTimeout(() => {
      this.connection()
      this.reconnectConfig.isReconnect = true;
      this.reconnectConfig.retry--
      console.log(`网络连接已断开，正在尝试重新连接(${this.reconnectConfig.retry})...`)
    }, reconnect.interval)
  }

  /**
   * 向服务器发送数据
   *
   * @param {Object} data
   */
  send(data) {
    this.ws && this.ws.send(JSON.stringify(data))
  }

  /**
   * 关闭连接
   */
  close() {
    this.ws.close()
    this.ws = null
  }
}
const webSocketEvent = new webSocket();
export default webSocketEvent
